const app = getApp(); // 获取全局应用实例
const baseURL = app.globalData.baseURL

// 引入快递公司数组
const KUAIDI_LIST = require('../../../utils/kuaidi.js')
// const mapUtils = require('../../../utils/mapUtils')  // 百度接口,不太好用
// 引入腾讯地图SDK
const QQMapWX = require('../../../utils/libs/qqmap-wx-jssdk.min.js'); // 需要下载好了
const qqmapsdk = new QQMapWX({ key: 'W7VBZ-R6HW7-ME4X7-HKMS5-ER73E-3HFCM' });
const qqMapKey = 'W7VBZ-R6HW7-ME4X7-HKMS5-ER73E-3HFCM'
const ak = 'P9lw9BXDplmIA3SR2dhujRR6WM9hlmBE' // 前往lbsyun.baidu.com申请(百度地图开放平台)

// 通用延迟函数
// const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

Page({
  data:{
    tracking_no: 'YT8760483550920',  //单号
    company_name: '',                //快递公司名
    company_logo: '',                //快递公司logo
    company_code: 'yuantong',      //快递公司简码
    phone: '15801890599',          //收件人电话（shunfeng顺丰sf要求要填）
    customerName: '周文忠',        //收件人姓名（jd京东要求要填）
    country: 'CN',                  //国际快递(dhl)需传入国家代码（如CN）   
    traces: [],

    markers: [],
    polyline: [],
    startPoint: { latitude: 29.557940, longitude: 103.772538 }, // 起点A
    endPoint: { latitude: 38.879988, longitude: 115.471464 },     // 终点B
    centerLat: 34.341, // 默认中心点（会被计算覆盖）
    centerLng: 108.939,
    scale: 10,          // 默认缩放级别
    // includePoints: [],
  },

  onLoad(options) {
    // this.setData({ tracking_no: options.trackingNo });  // 先注释掉，后再解开
    this.loadLogisticsData()
  },

  async loadLogisticsData() {
    const token = wx.getStorageSync('token').access
    try {
      const res = await wx.request({
        url: `${baseURL}api/logistics/`,
        method: 'GET',
        data:{
          tracking_no: this.data.tracking_no,
          company_code: this.data.company_code,
          phone: this.data.phone,
          customerName: this.data.customerName,
          country:this.data.country
        },
        header: { 'Authorization': 'Bearer ' + token },
        success: res => {
          // console.log('res:',res)
          if (res.statusCode === 200 && res.data.company) {
            const company = KUAIDI_LIST.find(item => item.com === res.data.company.toLowerCase())
            const company_name = company.name  // 快递公司名
            const company_logo = company.logo  // 快递公司logo
            const traces = res.data.traces     // 物流轨迹
            this.setData({ traces, company_name, company_logo });   // 轨迹 和 快递公司名 和 logo
            // 1.处理物流数据
            this.enrichTracesWithCoords(traces).then(enrichedTraces => {
              // console.log('增强后的轨迹数据enrichedTraces:', enrichedTraces);
              this.processMapData(enrichedTraces);  // 2.填写轨迹
            });
          }else{
            wx.showToast({ title: res.data.msg, icon: 'none', duration:5000 });
          }
        }
      });
    } catch (err) {
      wx.showToast({ title: '数据加载失败', icon: 'none' });
    }
  },

  //1.提取detail和areaName里的地址,合并在一起
  async enrichTracesWithCoords(traces) {
    // 批量提取detail里带有【】的所有地址
    const arr1 = traces.flatMap( t => this.extractAddress(t.detail) ).filter(addr => addr);
    // console.log('arr1:', arr1)  
    // 批量提取areaName里去掉","的所有地址
    const arr2 = traces.flatMap(t => {
      if (!t.areaName || typeof t.areaName !== 'string') return []
        const cleaned = t.areaName.trim().replace(/,/g, '') // 去前后空格+去逗号
      return cleaned ? [cleaned] : []  // 二次过滤空字符串
    })
    // console.log('arr2:', arr2)
    // 1. 合并数组
    const merged = [...arr1, ...arr2];
    // 2. 过滤非地址项（排除日期格式）
    const dateRegex = /\d+月\d+日/;
    const filtered = merged.filter(item => !dateRegex.test(item) && !item.includes('日'));
    // 3. 去重处理 [[7]]
    const seen = new Set();
    const uniqueAddresses = [];
    for (const item of filtered) {
      const key = item.replace(/(省|市|区|县|镇|乡|村)+/g, '')
                      .replace(/转运中心|分部|营业部/g, '').replace(/\s+/g, '');
      if (!seen.has(key)) {  // 有重复的不添加进来
        seen.add(key);
        uniqueAddresses.push(item);
      }
    }
    // console.log('uniqueAddresses:', uniqueAddresses)

    // 批量请求地理编码（并行处理）
    const coordPromises = uniqueAddresses.map(this.geocodeWithCache);
    const coordResults = await Promise.all(coordPromises);

    // 构建地址→坐标映射
    const addressCoordMap = uniqueAddresses.reduce((map, addr, i) => {
        map[addr] = coordResults[i];
      return map;
    }, {});
    // 回填坐标到原数据
    return traces.map(t => ({
      ...t,
      locations: t.areaName ? addressCoordMap[t.areaName.trim().replace(/,/g, '')] :
      this.extractAddress(t.detail) ?
      addressCoordMap[this.extractAddress(t.detail)] : { latitude: null, longitude: null }
    }));
  },

  // 用腾讯地图地址转坐标(有次数的限制)
  // geocodeAddress(address) {
  //   return new Promise((resolve, reject) => {
  //     qqmapsdk.geocoder({
  //       address: address,
  //       success: res => res.result ? resolve(res.result.location) : resolve({}),
  //       fail: err => reject(err)
  //     });
  //   });
  // },

  // 用百度地图地址转坐标
  geocodeAddress(address) {
    return new Promise((resolve, reject) => {
      wx.request({
      url: 'https://api.map.baidu.com/geocoding/v3/',
      data:{
        address: address,
        output: 'json',
        ak: ak,
      },
      success: res => { res.data.result ? resolve(res.data.result.location) : resolve({})},
      fail: err => reject(err)
      });
    });
  },

  // 使用正则从detail字段提取地址（示例匹配市级行政区）
  extractAddress(detail) {
    const regex = /【(.*?)】/g;  // 匹配【】包裹的地名
    const matches = [...detail.matchAll(regex)];
    return matches.map(m => m[1]);  //返回所有带【】的地名数组
  },

  async geocodeWithCache(address) {
    // 添加缓存层（有效期24小时）
    const geocodeCache = new Map()
    if (geocodeCache.has(address)) {
      return geocodeCache.get(address);
    }
    try {
      const { lat, lng } = await this.geocodeAddress(address);
      const result = { latitude:lat, longitude:lng };
      geocodeCache.set(address, result);
      return result;
    } catch (error) {
      console.error(`地址解析失败: ${address}`, error);
      return { latitude: null, longitude: null }; // 错误处理
    }
  },

  // 2.填写轨迹
  async processMapData(enrichedTraces) {
    // 2.1 过滤无 locations 的对象
    const filteredTraces = await enrichedTraces.filter(item => 
      item.locations && 
      typeof item.locations.latitude === 'number' && 
      typeof item.locations.longitude === 'number'
    );
    // 2.2 根据 locations 去重
    const seen = new Map();
    const validTraces = await filteredTraces.filter(item => {
      const key = `${item.locations.latitude.toFixed(6)}|${item.locations.longitude.toFixed(6)}`;
      return seen.has(key) ? false : seen.set(key, true);
    });
    // console.log('validTraces:', validTraces)
    // 起点A和终点B
    const B_b = validTraces[0].locations
    const A_a = validTraces[validTraces.length - 1].locations
    const B = `${B_b.latitude.toFixed(6)},${B_b.longitude.toFixed(6)}`
    const A = `${A_a.latitude.toFixed(6)},${A_a.longitude.toFixed(6)}`
    this.setData({
      markers: [
        this.createMarker(A_a, 'start'),
        this.createMarker(B_b, 'end')
      ]
    })
    this.requestRoute(A, B)
  },

  // 创建标记
  createMarker(point, type) {
    return {
      id: type === 'start' ? 0 : 1,  // 唯一ID标识
      latitude: point.latitude,
      longitude: point.longitude,
      iconPath: type === 'start' ? '/static/images/start.png' : '/static/images/end.png',
      width: 20,
      height: 20,
      anchor: { x: 0.5, y: 1 },
      callout: {
        content: type === 'start' ? '起点' : '终点',
        bgColor: type === 'start' ? '#09BB07' : '#FF0000'
      }
    }
  },

  // 发起路径规划请求(已用)
  requestRoute(A, B) {
    wx.request({
      url: 'https://api.map.baidu.com/direction/v2/driving',
      data:{
        ak: ak,
        origin: A,
        destination: B,
        coord_type: 'bd09ll', // 指定返回坐标类型
        ret_coordtype: 'bd09ll',
        tactics_incity: 0,    // 0-推荐路线
        output: 'json'
      },
      success: res => {
        if (res.data.status === 0) {
          this.processRouteData(res.data.result);
        } else {
          console.error('API错误:', res.data);
        }
      }
    });
  },

  // 处理返回的路线数据(已用)
  processRouteData(result) {
    const route = result.routes[0];
    // 1. 获取原始路径点（包含去重和过滤）
    let points = [];
    route.steps.forEach(step => {
      const stepPoints = step.path.split(';')
        .map(p => {
          const [lng, lat] = p.split(',');
          return { 
            latitude: parseFloat(lat), 
            longitude: parseFloat(lng)
          };
        })
        .filter(p => this.isValidCoordinate(p)); // 过滤无效坐标
      
      // 去除首尾重复点
      if (points.length > 0 && stepPoints.length > 0) {
        const last = points[points.length - 1];
        const first = stepPoints[0];
        if (last.latitude === first.latitude && last.longitude === first.longitude) {
          stepPoints.shift();
        }
      }
      points.push(...stepPoints);
    });

    // 2. 强制包含起终点（防止API遗漏）
    // points = [
    //   this.data.startPoint,
    //   ...points,
    //   this.data.endPoint
    // ].filter((p, i, arr) => 
    //   // 去重：避免重复添加相同坐标
    //   i === arr.findIndex(item => 
    //     item.latitude === p.latitude &&
    //     item.longitude === p.longitude
    //   )
    // );

    // 3. 计算地理边界（包含所有有效点）
    // const lats = points.map(p => p.latitude);
    // const lngs = points.map(p => p.longitude);
    // const bounds = {
    //   minLat: Math.min(...lats),
    //   maxLat: Math.max(...lats),
    //   minLng: Math.min(...lngs),
    //   maxLng: Math.max(...lngs)
    // };
    const bounds = this.validateBounds(points)
    // 4. 精确中心点计算（考虑地理权重）
    const center = this.calculateGeoCenter(points);

    // 5. 动态缩放级别计算
    // const scale = this.calculateZoomLevel(bounds);
    const baseZoom = this.calculateZoomLevel(bounds);
    const finalZoom = baseZoom - 5.5; // 精确中间值
    // 6. 更新视图
    this.setData({
      center,
      scale: Math.min(Math.max(finalZoom, 3), 20), // 限制在3-20级
      polyline: [{
        points: points,
        color: '#09BB07FF',   // 使用带透明度的颜色值
        width: 2,
        arrowLine: false,
        // arrowIconPath: '/static/images/back.png', // 可选自定义箭头图
        // borderWidth: 2,       // 边框宽度
        // borderColor: '#FFFFFF'// 边框颜色（增强视觉对比）
      }],
      includePoints: [
        { latitude: bounds.minLat, longitude: bounds.minLng },
        { latitude: bounds.maxLat, longitude: bounds.maxLng }
      ]
    });
  },

  // 坐标有效性验证(已用)
  isValidCoordinate(point) {
    return !isNaN(point.latitude) && 
          !isNaN(point.longitude) &&
          point.latitude >= -90 &&
          point.latitude <= 90 &&
          point.longitude >= -180 &&
          point.longitude <= 180;
  },

  // 地理权重中心计算(已用)
  calculateGeoCenter(points) {
    const total = points.length;
    let x = 0, y = 0, z = 0;

    points.forEach(p => {
      const latRad = p.latitude * Math.PI / 180;
      const lngRad = p.longitude * Math.PI / 180;
      
      x += Math.cos(latRad) * Math.cos(lngRad);
      y += Math.cos(latRad) * Math.sin(lngRad);
      z += Math.sin(latRad);
    });

    x /= total;
    y /= total;
    z /= total;

    const centerLng = Math.atan2(y, x) * 180 / Math.PI;
    const hyp = Math.sqrt(x * x + y * y);
    const centerLat = Math.atan2(z, hyp) * 180 / Math.PI;

    return { latitude: centerLat, longitude: centerLng };
  },

  // 动态缩放级别计算(已用)
  calculateZoomLevel(bounds) {
  const latSpan = bounds.maxLat - bounds.minLat;
  const lngSpan = bounds.maxLng - bounds.minLng;
  
  // 返回带小数的原始缩放级别（如12.7）
  if (latSpan > 2 || lngSpan > 2) return 10.5;    // 半级缓冲
  if (latSpan > 0.5 || lngSpan > 0.5) return 12.3;
  if (latSpan > 0.1 || lngSpan > 0.1) return 14.8;
  return 16.0;
  },

  // 新增边界校验方法(已用)
  validateBounds(points) {
    const MARGIN = 0.0002; // 约20米缓冲
    
    return {
      minLat: Math.min(...points.map(p => p.latitude)) - MARGIN,
      maxLat: Math.max(...points.map(p => p.latitude)) + MARGIN,
      minLng: Math.min(...points.map(p => p.longitude)) - MARGIN,
      maxLng: Math.max(...points.map(p => p.longitude)) + MARGIN
    };
  },

  zoomIn() {
    const newScale = Math.min(this.data.scale + 1, 20); // 最大缩放级别20
    this.setData({ scale: newScale });
  },
  
  zoomOut() {
    const newScale = Math.max(this.data.scale - 1, 3); // 最小缩放级别3
    this.setData({ scale: newScale });
  },

  // 点击地图查看当前视野范围(已用页面)
  onMapTap() {
    const mapContext = wx.createMapContext('bmap', this);
    mapContext.getRegion({
      success: res => {
        console.log('当前地图视野范围:', {
          northeast: res.northeast,
          southwest: res.southwest
        });
      }
    });
  },

  // 返回上一页
  navigateBack() {
    wx.navigateBack()
  },

});
